package cg;

import org.apache.commons.cli.*;
import spoon.Launcher;
import spoon.processing.AbstractProcessor;
import spoon.reflect.declaration.CtMethod;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Map;


/**
 * Spoon处理器
 *
 * @author 罗贤超
 * @since 2023/10/30 11:34
 */
public class SpoonCGProcessor extends AbstractProcessor<CtMethod<?>> { // 泛型CtMethod 表示对方法级别的处理

    private final SpoonCGVisitor spoonCGVisitor = new SpoonCGVisitor();

    @Override
    public void process(CtMethod element) {
        element.accept(spoonCGVisitor);
    }

    public void build(String inputPath,String outputPath) throws IOException {

        Launcher launcher = new Launcher();

        // 设置源码目录
        launcher.addInputResource(inputPath);
        // 设置输出目录（可选）  该输出就是你对代码修改过后的结果，如果你只是对代码进行读取操作那么不需要设备该目录
//        launcher.setSourceOutputDirectory(outputPath);

//         添加自定义Processor (MySpoonProcessor)
        launcher.addProcessor(this);

        // 运行Spoon
        launcher.run();

        // 获取方法节点数据
        Map<String, SpoonCGNode> spoonCGNodeMap = this.spoonCGVisitor.getSpoonCGNodeMap();

        FileUtils.writeDotFile(inputPath,outputPath, spoonCGNodeMap);


    }

    public static void delete(String path) throws IOException {
        Path dir = Paths.get(path);
        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                Files.delete(file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                if (!dir.equals(Paths.get(path))) {
                    Files.delete(dir);
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    public static void main(String[] args) {
        try{
            /*Options options = new Options();
            {
                final Option i = new Option("i", "directory", true,
                        "source directory");
                i.setArgName("directory");
                i.setArgs(1);
                i.setRequired(true);
                options.addOption(i);
            }

            {
                final Option o = new Option("o", "ControlFlowGraph", true,
                        "target directory");
                o.setArgName("file");
                o.setArgs(1);
                o.setRequired(true);
                options.addOption(o);
            }
            final CommandLineParser parser = new PosixParser();
            final CommandLine cmd = parser.parse(options, args);
            String inputPath = cmd.getOptionValue("i");
            String outputPath = cmd.getOptionValue("o");*/
            String inputPath = "input/";
            String outputPath = "output/CG/";
            delete(outputPath);
            SpoonCGProcessor spoonCGProcessor = new SpoonCGProcessor();

            spoonCGProcessor.build(inputPath,outputPath);
        }catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(0);
        }
    }
}